﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace BASIC_CORE.Domain.Caching.Repositories
{
    /// <summary>
    /// 缓存服务仓储接口
    /// </summary>
    public interface IServiceStackRedisCacheRepository
    {

        #region String 操作

        /// <summary>
        /// 插入数据
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="expirySeconds"></param>
        /// <returns></returns>
        Task SetString(string key, string value, int expirySeconds = -1);

        /// <summary>
        /// 插入数据
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="expireIn"></param>
        /// <returns></returns>
        Task SetString(string key, string value, TimeSpan? expireIn);

        /// <summary>
        /// 根据key查询数据value
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        Task<string> GetString(string key);

        /// <summary>
        /// 根据key删除数据
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        Task<bool> Remove(string key);

        /// <summary>
        /// 根据key集合删除数据
        /// </summary>
        /// <param name="keys"></param>
        /// <returns></returns>
        Task RemoveAll(string[] keys);

        #endregion String 操作

        #region Store-Object 操作

        /// <summary>
        /// 自动根据Id字段产生主键字符串，如果Id是int，没值，则默认就是0
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="entity"></param>
        /// <returns></returns>
        Task<T> Store<T>(T entity) where T : class, new();

        /// <summary>
        /// 可以对基础对象做StoreAll
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="entities"></param>
        /// <returns></returns>
        Task StoreAll<T>(IEnumerable<T> entities) where T : class, new();

        /// <summary>
        /// 可以Store泛型对象，此对象一定要包含Id字段，否则会报错。
        /// e.g.RedisHelper.StoreObject(new {Id = 101,Name = "name_11" });
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        Task<object> StoreObject(object entity);

        /// <summary>
        /// 根据key查询数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        Task<T> Get<T>(string key);

        /// <summary>
        /// 根据id查询
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="id"></param>
        /// <returns></returns>
        Task<T> GetById<T>(object id) where T : class, new();

        /// <summary>
        /// 常用。后台关联出表数据时，可以用此函数取出对应用户，然后对表数据刷上用户名。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="ids"></param>
        /// <returns></returns>
        Task<IList<T>> GetByIds<T>(ICollection ids) where T : class, new();

        /// <summary>
        /// 常用。基础数据有时可以直接GetAll出来，然后对IList做过滤排序。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        Task<IList<T>> GetAll<T>() where T : class, new();

        /// <summary>
        ///  如果不存在key缓存，则添加，返回true。如果已经存在key缓存，则不作操作，返回false。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="entity"></param>
        /// <param name="expirySeconds"></param>
        /// <returns></returns>
        Task<bool> AddIfNotExist<T>(string key, T entity, int expirySeconds = -1);

        /// <summary>
        /// 如果不存在key缓存，则添加，返回true。如果已经存在key缓存，则不作操作，返回false。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="entity"></param>
        /// <param name="expireIn"></param>
        /// <returns></returns>
        Task<bool> AddIfNotExist<T>(string key, T entity, TimeSpan? expireIn);

        /// <summary>
        /// 插入数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="entity"></param>
        /// <param name="expirySeconds"></param>
        /// <returns></returns>
        Task Set<T>(string key, T entity, int expirySeconds = -1);

        /// <summary>
        /// 插入数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="entity"></param>
        /// <param name="expireIn"></param>
        /// <returns></returns>
        Task Set<T>(string key, T entity, TimeSpan? expireIn);

        /// <summary>
        /// key如果不存在，则添加value，返回true；如果key已经存在，则不添加value，返回false。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="entity"></param>
        /// <param name="expirySeconds"></param>
        /// <returns></returns>
        Task<bool> SetIfNotExists<T>(string key, T entity, int expirySeconds = -1);

        /// <summary>
        /// key如果不存在，则添加value，返回true；如果key已经存在，则不添加value，返回false。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="entity"></param>
        /// <param name="expireIn"></param>
        /// <returns></returns>
        Task<bool> SetIfNotExists<T>(string key, T entity, TimeSpan? expireIn);

        /// <summary>
        /// 后台修改基础数据，要清基础数据的缓存时，可以全清。也可以单笔清DeleteById。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        Task DeleteAll<T>() where T : class, new();

        /// <summary>
        /// 根据id删除数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="id"></param>
        /// <returns></returns>
        Task DeleteById<T>(object id) where T : class, new();

        /// <summary>
        /// 根据id集合删除数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="ids"></param>
        /// <returns></returns>
        Task DeleteByIds<T>(ICollection ids) where T : class, new();

        #endregion Store-Object 操作

        #region Hash-Store 操作

        /// <summary>
        /// 将一个对象存入Hash。比如对象User有Id=1和Name="aa"属性，则生成的Hash存储是key为urn:user:1，
        /// 第一行field为Id，它的value是1，第二行field为Name，它的value是"aa"。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="entity"></param>
        /// <returns></returns>
        Task StoreAsHash<T>(T entity);

        /// <summary>
        /// 根据Id获取对象(存储的时候使用Hash)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="id"></param>
        /// <returns></returns>
        Task<T> GetFromHash<T>(object id);

        /// <summary>
        /// 根据HashId 获取hash对象总数量
        /// </summary>
        /// <param name="hashId"></param>
        /// <returns></returns>
        Task<int> GetHashCount(string hashId);

        /// <summary>
        /// 根据HashId 获取 hash keys
        /// </summary>
        /// <param name="hashId"></param>
        /// <returns></returns>
        Task<List<string>> GetHashKeys(string hashId);

        /// <summary>
        /// 根据HashId 获取 hash values
        /// </summary>
        /// <param name="hashId"></param>
        /// <returns></returns>
        Task<List<string>> GetHashValues(string hashId);

        /// <summary>
        /// 取一个函数的单个字段值时，用此函数。
        /// </summary>
        /// <param name="hashId"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        Task<string> GetValueFromHash(string hashId, string key);

        /// <summary>
        /// 取一个Hash的多个字段值时用此函数。
        /// </summary>
        /// <param name="hashId"></param>
        /// <param name="keys"></param>
        /// <returns></returns>
        Task<List<string>> GetValuesFromHash(string hashId, params string[] keys);

        /// <summary>
        /// 根据HashId 获取 hash 字典值
        /// </summary>
        /// <param name="hashId"></param>
        /// <returns></returns>
        Task<Dictionary<string, string>> GetEntriesFromHash(string hashId);

        /// <summary>
        /// 将一组键值对写入一个hash。比如Dictionary<string,string>(){{"d1","1"},{"d2","2"}};，则生成的Hash存储是key为参数hashId，
        /// 第一行field为d1，它的value是1，第二行field为d2，它的value是2。</summary>
        /// <param name="hashId"></param>
        /// <param name="keyValuePairs"></param>
        /// <returns></returns>
        Task SetRangeInHash(string hashId, IEnumerable<KeyValuePair<string, string>> keyValuePairs);

        /// <summary>
        /// 指定hashId key 存储Hash值
        /// </summary>
        /// <param name="hashId"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        Task SetEntryInHash(string hashId, string key, string value);

        /// <summary>
        /// 指定hashId key，如果不存在则存储Hash值
        /// </summary>
        /// <param name="hashId"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        Task SetEntryInHashIfNotExists(string hashId, string key, string value);

        /// <summary>
        /// 指定Key 移除 hash值
        /// </summary>
        /// <param name="hashId"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        Task RemoveEntryFromHash(string hashId, string key);

        #endregion Hash-Store 操作

        #region List操作

        /// <summary>
        /// 查询集合
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        Task<List<string>> GetAllItemsFromList(string key);

        /// <summary>
        /// 添加value 到现有List
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        Task AddItemToList(string key, string value);

        /// <summary>
        /// 添加多个value 到现有List
        /// </summary>
        /// <param name="key"></param>
        /// <param name="values"></param>
        /// <returns></returns>
        Task AddRangeToList(string key, List<string> values);

        /// <summary>
        /// 从队列取数据 先进先出
        /// </summary>
        /// <param name="listId"></param>
        /// <param name="timeoutSeconds"></param>
        /// <returns></returns>
        Task<string> DequeueItemFromList(string listId, int timeoutSeconds = -1);

        /// <summary>
        /// 从队列取数据 先进先出
        /// </summary>
        /// <param name="listId"></param>
        /// <param name="timeOut"></param>
        /// <returns></returns>
        Task<string> DequeueItemFromList(string listId, TimeSpan? timeOut = null);

        /// <summary>
        /// 存储数据到队列 先进先出
        /// </summary>
        /// <param name="listId"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        Task EnqueueItemOnList(string listId, string value);

        /// <summary>
        /// 根据Id移除集合value
        /// </summary>
        /// <param name="listId"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        Task RemoveItemFromList(string listId, string value);

        #endregion List操作

        #region Inc-Dec 操作

        /// <summary>
        /// 根据key增量
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        Task<long> IncrementValue(string key);

        /// <summary>
        /// 根据key增量多条
        /// </summary>
        /// <param name="key"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        Task<long> IncrementValueBy(string key, int count);

        /// <summary>
        /// 根据key递减
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        Task<long> DecrementValue(string key);

        /// <summary>
        /// 根据key递减多条
        /// </summary>
        /// <param name="key"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        Task<long> DecrementValueBy(string key, int count);

        #endregion Inc-Dec 操作

        #region Other 操作

        /// <summary>
        /// 附加值
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        Task<long> AppendToValue(string key, string value);

        /// <summary>
        /// 查询
        /// </summary>
        /// <returns></returns>
        Task<string> GetRandomKey();

        /// <summary>
        /// 根据keys集合查询数据
        /// </summary>
        /// <param name="keys"></param>
        /// <returns></returns>
        Task<List<string>> GetValues(List<string> keys);

        /// <summary>
        /// 根据keys集合查询数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="keys"></param>
        /// <returns></returns>
        Task<List<T>> GetValues<T>(List<string> keys);

        /// <summary>
        /// 查询集合
        /// </summary>
        /// <returns></returns>
        Task<List<string>> GetAllKeys();

        /// <summary>
        /// 插入集合
        /// </summary>
        /// <param name="keys"></param>
        /// <param name="values"></param>
        /// <returns></returns>
        Task SetAll(IEnumerable<string> keys, IEnumerable<string> values);

        /// <summary>
        /// 插入Dictionary
        /// </summary>
        /// <param name="map"></param>
        /// <returns></returns>
        Task SetAll(Dictionary<string, string> map);

        /// <summary>
        /// 设置到期
        /// </summary>
        /// <param name="key"></param>
        /// <param name="seconds"></param>
        /// <returns></returns>
        Task<bool> Expire(string key, int seconds);

        /// <summary>
        /// ExpireAt
        /// </summary>
        /// <param name="key"></param>
        /// <param name="unixTime"></param>
        /// <returns></returns>
        Task<bool> ExpireAt(string key, long unixTime);

        /// <summary>
        /// ExpireEntryAt
        /// </summary>
        /// <param name="key"></param>
        /// <param name="expireAt"></param>
        /// <returns></returns>
        Task<bool> ExpireEntryAt(string key, DateTime expireAt);

        /// <summary>
        /// ExpireEntryIn
        /// </summary>
        /// <param name="key"></param>
        /// <param name="expireIn"></param>
        /// <returns></returns>
        Task<bool> ExpireEntryIn(string key, TimeSpan expireIn);

        /// <summary>
        /// 按正则条件删除。可以删除一张表前缀
        /// </summary>
        /// <param name="pattern"></param>
        /// <returns></returns>
        Task RemoveByRegex(string pattern);

        #endregion Other 操作

    }
}
